// backend/log_generator.go
package main

import (
	"fmt"
	"math/rand"
	"time"

	"github.com/google/uuid"
)

// 模拟数据字典（用于生成随机日志）
var (
	// 常见前端框架
	frameworks = []string{"Vue", "React", "Angular", "Svelte", "jQuery", "VanillaJS"}
	// 常见浏览器UA
	userAgents = []string{
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/125.0",
		"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15",
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/124.0.0.0 Safari/537.36",
	}
	// 模拟IP段（192.168.1.x）
	ipPrefix = "192.168.1."
)

// GenerateRandomLog 生成单条随机模拟日志
func GenerateRandomLog() TrafficLog {
	rand.NewSource(time.Now().UnixNano())
	return TrafficLog{
		Id:         uuid.NewString(),                                               // 生成UUID作为唯一ID
		Ip:         ipPrefix + fmt.Sprintf("%d", rand.Intn(255)),                   // 随机IP（192.168.1.0-255）
		Framework:  frameworks[rand.Intn(len(frameworks))],                         // 随机框架
		UserAgent:  userAgents[rand.Intn(len(userAgents))],                         // 随机UA
		AccessTime: time.Now().Add(-time.Duration(rand.Intn(86400)) * time.Second), // 最近24小时内随机时间
	}
}

// StartLogGenerator 启动日志生成协程
// 参数：logChan 日志通道（生成的日志写入此通道）
func StartLogGenerator(logChan chan<- TrafficLog) {
	total := Config.GenLogNum
	goroutineNum := Config.GenGoroutineNum
	logPerGoroutine := total / goroutineNum

	// 启动N个协程并发生成日志
	/*
		闭包特性：匿名函数捕获了外部变量i，但由于协程启动和循环执行的异步性，若直接使用i可能导致输出错误（协程执行时i已变化）
		解决方案：通过函数参数num将当前logPerGoroutine的值传递给匿名函数，避免对循环变量的依赖
	*/
	for i := 0; i < goroutineNum; i++ {
		go func(num int) {
			count := 0
			for count < num {
				log := GenerateRandomLog()
				logChan <- log // 写入日志通道
				count++
				time.Sleep(1 * time.Millisecond) // 控制生成速度，避免通道阻塞
			}
			fmt.Printf("协程%d完成日志生成，共生成%d条\n", i+1, num)
		}(logPerGoroutine) //匿名函数定义后，紧跟 (logPerGoroutine) 表示立即调用该函数，传入参数 logPerGoroutine
	}

	// 等待所有日志生成完成后关闭通道
	/*time.Ticker：创建一个周期性触发的定时器，100 * time.Millisecond 表示每 100 毫秒触发一次
	ticker.C：定时器的通道，每次触发会向该通道发送当前时间
	defer语句：确保ticker.Stop()在函数退出时执行，释放定时器资源，避免内存泄漏
	for 循环遍历通道：for range ticker.C 会持续从通道接收数据，实现定期检查逻辑
	*/
	go func() {
		ticker := time.NewTicker(100 * time.Millisecond)
		defer ticker.Stop()

		totalGenerated := 0
		for range ticker.C {
			if totalGenerated >= total {
				close(logChan)
				fmt.Println("所有模拟日志生成完成，关闭日志通道")
				return
			}
			totalGenerated = total - len(logChan) // 估算已生成数量（通道剩余量=总-已生成）
		}
	}()
}

/*
随机数生成：rand.Intn(n) 生成 0~n-1 的随机整数，结合时间种子保证随机性
协程（Goroutine）：go关键字启动轻量级线程，实现高效并发
通道（Channel）：chan<- TrafficLog 定义只写通道，用于协程间安全传递数据
匿名函数：作为协程入口，通过参数传递每个协程的任务量
时间控制：time.Sleep 控制速度，time.Ticker 实现定期检查
资源释放：defer ticker.Stop() 确保定时器资源被正确释放
*/
